/* UART Events Example

   This example code is in the Public Domain (or CC0 licensed, at your option.)

   Unless required by applicable law or agreed to in writing, this
   software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
   CONDITIONS OF ANY KIND, either express or implied.
*/
#include "load_cert.h"

static const char *TAG = "uart_events";

/**
 * This example shows how to use the UART driver to handle special UART events.
 *
 * It also reads data from UART0 directly, and echoes it to console.
 *
 * - Port: UART0
 * - Receive (Rx) buffer: on
 * - Transmit (Tx) buffer: off
 * - Flow control: off
 * - Event queue: on
 * - Pin assignment: TxD (default), RxD (default)
 */

#define EX_UART_NUM UART_NUM_0
#define PATTERN_CHR_NUM (3) /*!< Set the number of consecutive and identical characters received by receiver which defines a UART pattern*/

#define BUF_SIZE (1024)
#define RD_BUF_SIZE (BUF_SIZE)
static QueueHandle_t uart0_queue;
unsigned char get_ca_cert = 0;      //0 为收到或已完成接收
unsigned char get_private_cert = 0; //0 为收到或已完成接收

static void uart_event_task(void)
{
    uart_event_t event;
    size_t buffered_size;
    uint8_t *dtmp = (uint8_t *)malloc(RD_BUF_SIZE);
    if (wireless_state.aws_cert == no_inform)
    {
        //ESP_LOGI(TAG, "no aws cert waiting for input...");
    }
    while (wireless_state.aws_cert == no_inform)
    {
        //Waiting for UART event.
        if (xQueueReceive(uart0_queue, (void *)&event, (portTickType)portMAX_DELAY))
        {
            bzero(dtmp, RD_BUF_SIZE);
            // //ESP_LOGI(TAG, "uart[%d] event:", EX_UART_NUM);
            switch (event.type)
            {
            //Event of UART receving data
            /*We'd better handler data event fast, there would be much more data events than
                other types of events. If we take too much time on data event, the queue might
                be full.*/
            case UART_DATA:
                // //ESP_LOGI(TAG, "[UART DATA]: %d", event.size);
                uart_read_bytes(EX_UART_NUM, dtmp, event.size, portMAX_DELAY);
                // //ESP_LOGI(TAG, "[DATA EVT]:");
                int temp = 0;
                int ret = 1;
                static unsigned int ca_length = 0;
                static unsigned int private_length = 0;
                temp = strlen((char *)dtmp); //统计收到的字符串长度
                // //ESP_LOGI(TAG, "received date is %.*s", temp, dtmp);
                ///*串口写入CA证书*/
                ret = strncmp((char *)dtmp, "-----BEGIN CERTIFICATE-----", 27); //判断CA证书开头
                if (ret == 0)
                {
                    ca_length = 0;   //复位开始接收证书
                    get_ca_cert = 1; //接收证书标志
                }
                if (get_ca_cert == 1) //开始接收证书
                {
                    for (int i = 0; i < temp; i++)
                    {
                        ca_cert[ca_length] = dtmp[i]; //将收到的字符串写入temp_cert
                        ca_length++;                  //移位
                    }
                }
                //ESP_LOGI(TAG, "ca length is %d", ca_length);
                ///*完成接收CA证书*/
                if ((ca_length >= 1224) && (get_ca_cert == 1))
                {
                    ca_cert[1225] = '\n';
                    get_ca_cert = 2;
                    ca_length = 0;
                    //ESP_LOGI(TAG, "get ca cert");
                    //ESP_LOGI(TAG, "ca is %s", ca_cert);
                }
                ret = strncmp((char *)dtmp, "-----BEGIN RSA PRIVATE KEY-----", 31); //判断private证书开头
                if (ret == 0)
                {
                    private_length = 0;   //复位开始接收证书
                    get_private_cert = 1; //接收证书标志
                    //ESP_LOGI(TAG, "start receive private");
                }
                if (get_private_cert == 1) //开始接收证书
                {
                    for (int i = 0; i < temp; i++)
                    {
                        private_cert[private_length] = dtmp[i]; //将收到的字符串写入
                        private_length++;                       //移位
                    }
                    // //ESP_LOGI(TAG, "temp private is %s", private_cert);
                }
                //ESP_LOGI(TAG, "private length is %d", private_length);
                ///*完成接收private证书*/
                if ((private_length >= 1675) && (get_private_cert == 1))
                {
                    // ca_cert[1676] = '\n';
                    get_private_cert = 2;
                    private_length = 0;
                    //ESP_LOGI(TAG, "get private cert");
                    //ESP_LOGI(TAG, "private is %s", private_cert);
                }
                // uart_write_bytes(EX_UART_NUM, (const char *)dtmp, event.size);
                break;
            //Event of HW FIFO overflow detected
            case UART_FIFO_OVF:
                //ESP_LOGI(TAG, "hw fifo overflow");
                // If fifo overflow happened, you should consider adding flow control for your application.
                // The ISR has already reset the rx FIFO,
                // As an example, we directly flush the rx buffer here in order to read more data.
                uart_flush_input(EX_UART_NUM);
                xQueueReset(uart0_queue);
                break;
            //Event of UART ring buffer full
            case UART_BUFFER_FULL:
                //ESP_LOGI(TAG, "ring buffer full");
                // If buffer full happened, you should consider encreasing your buffer size
                // As an example, we directly flush the rx buffer here in order to read more data.
                uart_flush_input(EX_UART_NUM);
                xQueueReset(uart0_queue);
                break;
            //Event of UART RX break detected
            case UART_BREAK:
                //ESP_LOGI(TAG, "uart rx break");
                break;
            //Event of UART parity check error
            case UART_PARITY_ERR:
                //ESP_LOGI(TAG, "uart parity error");
                break;
            //Event of UART frame error
            case UART_FRAME_ERR:
                //ESP_LOGI(TAG, "uart frame error");
                break;
            //UART_PATTERN_DET
            case UART_PATTERN_DET:
                uart_get_buffered_data_len(EX_UART_NUM, &buffered_size);
                int pos = uart_pattern_pop_pos(EX_UART_NUM);
                //ESP_LOGI(TAG, "[UART PATTERN DETECTED] pos: %d, buffered size: %d", pos, buffered_size);
                if (pos == -1)
                {
                    // There used to be a UART_PATTERN_DET event, but the pattern position queue is full so that it can not
                    // record the position. We should set a larger queue size.
                    // As an example, we directly flush the rx buffer here.
                    uart_flush_input(EX_UART_NUM);
                }
                else
                {
                    uart_read_bytes(EX_UART_NUM, dtmp, pos, 100 / portTICK_PERIOD_MS);
                    uint8_t pat[PATTERN_CHR_NUM + 1];
                    memset(pat, 0, sizeof(pat));
                    uart_read_bytes(EX_UART_NUM, pat, PATTERN_CHR_NUM, 100 / portTICK_PERIOD_MS);
                    //ESP_LOGI(TAG, "read data: %s", dtmp);
                    //ESP_LOGI(TAG, "read pat : %s", pat);
                }
                break;
            //Others
            default:
                //ESP_LOGI(TAG, "uart event type: %d", event.type);
                break;
            }
        }
        if ((get_private_cert == 2) && (get_ca_cert == 2))
        {
            //ESP_LOGI(TAG, "finished received aws cert");
            wireless_state.aws_cert = get_inform;
            NVS_Write_cert(); //写入证书
            // vTaskDelete(NULL);
        }
    }
    // free(dtmp);
    // dtmp = NULL;
    // vTaskDelete(NULL);
}

esp_err_t uart_load_cert(void)
{
    // esp_log_level_set(TAG, ESP_LOG_INFO);

    /* Configure parameters of an UART driver,
     * communication pins and install the driver */
    uart_config_t uart_config = {
        .baud_rate = 115200,
        .data_bits = UART_DATA_8_BITS,
        .parity = UART_PARITY_DISABLE,
        .stop_bits = UART_STOP_BITS_1,
        .flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
        .source_clk = UART_SCLK_APB,
    };
    //Install UART driver, and get the queue.
    uart_driver_install(EX_UART_NUM, BUF_SIZE * 2, BUF_SIZE * 2, 20, &uart0_queue, 0);
    uart_param_config(EX_UART_NUM, &uart_config);

    //Set UART log level
    // esp_log_level_set(TAG, ESP_LOG_INFO);
    //Set UART pins (using UART0 default pins ie no changes.)
    uart_set_pin(EX_UART_NUM, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);

    //Set uart pattern detect function.
    uart_enable_pattern_det_baud_intr(EX_UART_NUM, '+', PATTERN_CHR_NUM, 9, 0, 0);
    //Reset the pattern queue length to record at most 20 pattern positions.
    uart_pattern_queue_reset(EX_UART_NUM, 20);

    //Create a task to handler UART event from ISR
    // xTaskCreate(uart_event_task, "uart_event_task", 2048, NULL, 12, NULL);
    uart_event_task();
    return ESP_OK;
}
